package Calculate;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * Performs various byte-related calculations and conversions.
 * 
 * @author Tobias Edin
 */
public class ByteCalc {
	
	/**
	 * Converts a long to a byte array.
	 * @param value Value to convert.
	 * @return Byte array containing 'values' bytes.
	 * @throws IOException
	 */
	public static byte[] longToByteArray(long value) {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();  
		DataOutputStream dos = new DataOutputStream(bos); 
		byte[] data;
		
		try {
			dos.writeLong(value);
			dos.flush();  
			data = bos.toByteArray(); 
			dos.close();
			
		} catch (IOException e) {
			return null;
		}    
		
		return data;
	}
	
	/**
	 * Converts a byte array into a long.
	 * 
	 * @param data Byte array to convert.
	 * @return Long value of byte array.
	 */
	public static long byteArrayToLong(byte[] data) {
		ByteArrayInputStream bis;
		DataInputStream dis;
		
		/* If the array is less then 8 in size, extend it. */
		if (data.length > 8) {
			return -1;
		} else if (data.length < 8) {
			data = concatenate(new byte[8 - data.length], data);
		}
		
		bis = new ByteArrayInputStream(data);
		dis = new DataInputStream(bis);
		
		try {
			return dis.readLong();
		} catch (IOException e) {
			e.printStackTrace();
			return -1;
		}
	}
	
	/**
	 * Concatenates two byte arrays.
	 */
	public static byte[] concatenate(byte[] first, byte[] second) {
		byte[] ret = new byte[first.length + second.length];
		System.arraycopy(first, 0, ret, 0, first.length);
		System.arraycopy(second, 0, ret, first.length, second.length);

		return ret;
	}
	
	/**
	 * Retrieves a subset of an array. Start offset is inclusive, ending
	 * offset exclusive.
	 * 
	 * @param data Array containing the data.
	 * @param start Start offset for the sub array in data.
	 * @param stop End offset for the sub array in data.
	 * @return An array containing a subset of data's content.
	 */
	public static byte[] subArray(byte[] data, int start, int stop) {
		byte[] subset = new byte[stop - start];
		
		if (start > stop || data == null) {
			return null;
		} else {
			System.arraycopy(data, start, subset, 0, stop - start); 
			return subset;
		}
	}
}
